using System;
using System.IO;

using Microsoft.WowAddonStudio.Lua.RuntimeService.Common;
using Microsoft.WowAddonStudio.Lua.RuntimeService.ShellHost;
using Microsoft.WowAddonStudio.Lua.RuntimeService.Tests.Mocks;
using Microsoft.WowAddonStudio.Lua.RuntimeService.Tests.WowBench;
using Microsoft.WowAddonStudio.Lua.RuntimeService.WowBench.Resolvers;
using Microsoft.WowAddonStudio.Services;
using Microsoft.WowAddonStudio.Tests.Common.Mocks;
using NUnit.Framework;

namespace Microsoft.WowAddonStudio.Lua.RuntimeService.Tests
{
	[TestFixture]
	public sealed class LuaRuntimeTest : WoWBenchTestBase
	{
		#region Setup/Teardown

		[SetUp]
		public override void SetUp()
		{
			base.SetUp();
			SimpleTestServiceLocator.Register<IAddonStudioSettings>(new MockAddonStudioSettings(wowBenchPath));
			runtime = new LuaRuntime(Provider, resolverFactory, factory);
		}

		[TearDown]
		public override void TearDown()
		{
			base.TearDown();
			Environment.CurrentDirectory = savedPath;
		}

		#endregion

		private ILuaRuntime runtime;
		private IShellHostFactory factory;
		private IResolverFactory resolverFactory;


		[TestFixtureSetUp]
		public override void TestFixtureSetUp()
		{
			base.TestFixtureSetUp();
			resolverFactory = new ResolverFactory(Provider);
			factory = new MockShellHostFactory();
		}

		[Test(Description = "")]
		[ExpectedException(typeof (ArgumentNullException))]
		public void Test_AddLuaFileFailed()
		{
			runtime.AddLuaFile(null);
		}

		[Test(Description = "")]
		[ExpectedException(typeof (FileNotFoundException))]
		public void Test_AddLuaFileNotFound()
		{
			runtime.AddLuaFile("test12.lua");
		}

		[Test(Description = "")]
		public void Test_AddLuaFileSuccess()
		{
			try
			{
				RegisterServicesForEvaluation();
				runtime.AddLuaFile("Resources\\test.lua");
			}
			finally
			{
				Provider.Remove<ILuaRuntimeService>();
				Provider.Remove<EnvDTE.Project>();
			}
		}

		[Test(Description = "")]
		public void Test_CreationNormal()
		{
			Assert.AreEqual(wowBenchPath, runtime.WowBenchPath);
			Assert.IsNotNull(runtime.RuntimeController);
			Assert.IsNull(runtime.RuntimeShellHost);
			Assert.IsNotNull(runtime.ToolWindowControl);
		}

		[Test(Description = "")]
		[ExpectedException(typeof (LuaRuntimeInitializationException))]
		public void Test_CreationWithoutFactory()
		{
			runtime = new LuaRuntime(Provider, resolverFactory, null);
		}

		[Test(Description = "")]
		[ExpectedException(typeof (LuaRuntimeInitializationException))]
		public void Test_CreationWithoutProvider()
		{
			runtime = new LuaRuntime(null, resolverFactory, factory);
		}

		[Test(Description = "")]
		public void Test_CreationWithoutWoWBenchPathSet()
		{
			var settings = SimpleTestServiceLocator.Get<IAddonStudioSettings>();
			string runtimePath = Path.Combine(savedPath, @"Exe\WoWBench\");
			settings.CustomWowBenchPath = runtimePath;
			runtime = new LuaRuntime(Provider, resolverFactory, factory);
			Assert.AreEqual(runtimePath, runtime.WowBenchPath);
			Assert.AreEqual(runtimePath, settings.CustomWowBenchPath);
		}

		[Test(Description = "")]
		public void Test_EvaluateExpression()
		{
			try
			{
				RegisterServicesForEvaluation();

				runtime.EvaluateExpression("print(10);");
			}
			finally
			{
				Provider.Remove<ILuaRuntimeService>();
				Provider.Remove<EnvDTE.Project>();
			}
		}

		[Test(Description = "")]
		[ExpectedException(typeof (LuaRuntimeServiceNotFoundException))]
		public void Test_EvaluateExpressionServiceNotFound()
		{
			Provider.Remove<ILuaRuntimeService>();
			runtime.EvaluateExpression("print(10);");
		}

		[Test(Description = "")]
		public void Test_EvaluateExpressionWithNullExpression()
		{
			object expression = runtime.EvaluateExpression(null);
			Assert.IsNull((expression));
			expression = runtime.EvaluateExpression(string.Empty);
			Assert.IsNull((expression));
		}

		[Test(Description = "")]
		public void Test_RemoveLuaFile()
		{
			runtime.RemoveLuaFile("test.lua");
			//..........
		}

		/// <summary>
		/// Registers the services for evaluation.
		/// </summary>
		private static void RegisterServicesForEvaluation()
		{
			SimpleTestServiceLocator.Register<ILuaRuntimeService>(new MockLuaRuntimeService());
			var props = new MockProperties(DTE, null);
			props.Add("AddonTitle", CreateMockProperty(props, "AddonTitle", "WoWAddOn12"));
			props.Add("FullPath", CreateMockProperty(props, "FullPath", Environment.CurrentDirectory));
			var project = new MockOAProject(DTE, props);
			SimpleTestServiceLocator.Register<EnvDTE.Project>(project);
		}
	}
}